package com.yearner.reviewplan.user.data;

import com.yearner.reviewplan.common.util.AsyncWorker;
import com.yearner.reviewplan.common.util.MyJdbcUtil;
import com.yearner.reviewplan.user.model.UserId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * UserId 生成器
 * @author pengyg
 * @since 2019/10/16
 */
@Component
public class UserIdGenerator implements Callable<String> {
    private final static Logger logger = LoggerFactory.getLogger(UserIdGenerator.class);
    /**
     *  获取userId
     * @return UserId
     */
    public UserId generator() {
        try {
            return UserId.byId(call());
        } catch (Exception e) {
            throw new RuntimeException("ID生成出错啦",e.getCause());
        }
    }
    private LinkedList<String> mListQueue = new LinkedList<>();
    private Lock lock = new ReentrantLock();

    private static final String PREFIX = "U";
    /** 起始编号 */
    private static long START_NUM = 10086L;
    private static final int ADD_NUM = 1000;
    private static final int MIN_SIZE = 50;


    public UserIdGenerator(@Qualifier(value = "myTasks") Executor asyncTask) {
        asyncTask.execute(this::init);
    }
    private void init() {
        logger.info("批量初始化UserID....."+Thread.currentThread().getName());
        //初始化，获取 START_NUM ，添加进mList
        JdbcTemplate jdbcTemplate = new JdbcTemplate(MyJdbcUtil.sGetDataSource());
        String sql = "select count(*) from user";
        Object obj = jdbcTemplate.queryForMap(sql).get("count(*)");
        try {
            int count = Integer.parseInt(obj.toString());
            START_NUM = count + 1;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        update();
    }

    /*
    先初始化list，add相关数据，START_NUM + ADD_NUM
    不断取出，mListQueue.size() < MIN_SIZE 时，synchronized增添列表
     */

    /**
     * 往队列添加 ADD_NUM 个数据，并将 START_NUM 更新
     */
    private void update() {
        long point = START_NUM + ADD_NUM;
        logger.info("当前id标识： {} ，最大id标识： {}", START_NUM,point);
        List<String> updateData = new ArrayList<>();
        for (long i = START_NUM; i <= point; i++) {
            updateData.add(PREFIX + i);
        }
        mListQueue.addAll(updateData);

        START_NUM = point;
    }

    @Override
    public String call() {
        //在获取同步锁之后在判断是否需要添加一批
        if ( (mListQueue.size()< MIN_SIZE) && lock.tryLock()) {
            if (mListQueue.size()< MIN_SIZE) {
                update();
            }
            lock.unlock();
        }

        return mListQueue.poll();
//        try{
//            return mListQueue.poll();
//        }finally {
//            if (mListQueue.size() < 50) {
//                isNeedUpdate = true;
//            }
//        }

    }
}
